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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-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
1120 files changed, 329067 insertions, 0 deletions
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
+